package token.mobileapp.utils;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.KeepAliveHttpsTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import token.mobileapp.model.UserInfo;

import javax.net.ssl.*;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * token.mobileapp.utils
 * Author: AVAVT
 * Date: 7/13/11
 * Time: 9:15 PM
 */
public class NetworkUtils {
    private static final String NAMESPACE = "http://servlet.web.sc.com";
    private static final String SOAP_ACTION = "http://servlet.web.sc.com/sayHelloWorldFrom";

    NetworkUtils() {

    }

    public static UserInfo initialize(UserInfo userInfo, String accountCode) throws IOException {
        String soapAction = "http://servlet.web.sc.com/initAuthenticator";
        String methodName = "initAuthenticator";

        allowAllSSL();

        SoapObject request = new SoapObject(NAMESPACE, methodName);

        PropertyInfo userSecretKey = new PropertyInfo();
        userSecretKey.name = "secretKey";
        userSecretKey.type = PropertyInfo.STRING_CLASS;
        userSecretKey.setValue(userInfo.getSecretKey());
        request.addProperty(userSecretKey);

        PropertyInfo userAccountCode = new PropertyInfo();
        userAccountCode.name = "accountCode";
        userAccountCode.type = PropertyInfo.STRING_CLASS;
        userAccountCode.setValue(accountCode);
        request.addProperty(userAccountCode);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.setOutputSoapObject(request);

        KeepAliveHttpsTransportSE keepAliveHttpsTransportSE = new KeepAliveHttpsTransportSE(Constants.NETWORK_IP, Constants.NETWORK_PORT, Constants.NETWORK_SERVICE_ADDRESS, Constants.NETWORK_TIMEOUT);
        keepAliveHttpsTransportSE.debug = true;

        try {
            keepAliveHttpsTransportSE.call(soapAction, envelope);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
        try {
            SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
            String seed = resultsRequestSOAP.toString();
            if (seed == null || seed.equals("")) {
                return userInfo;
            } else {
                userInfo.setSeed(seed);
                userInfo.setEvent("0");
                return userInfo;
            }
        } catch (SoapFault soapFault) {
            soapFault.printStackTrace();
            System.out.println(keepAliveHttpsTransportSE.responseDump);
            return userInfo;
        }
    }

    public static UserInfo synchronize(UserInfo userInfo) throws IOException {
        String methodName = "syncAuthenticator";

        allowAllSSL();

        SoapObject request = new SoapObject(NAMESPACE, methodName);

        PropertyInfo userSecretKey = new PropertyInfo();
        userSecretKey.name = "secretKey";
        userSecretKey.type = PropertyInfo.STRING_CLASS;
        userSecretKey.setValue(userInfo.getSecretKey());
        request.addProperty(userSecretKey);

        PropertyInfo userSeed = new PropertyInfo();
        userSeed.name = "seed";
        userSeed.type = PropertyInfo.STRING_CLASS;
        userSeed.setValue(userInfo.getSeed());
        request.addProperty(userSeed);

        PropertyInfo userEvent = new PropertyInfo();
        userEvent.name = "event";
        userEvent.type = PropertyInfo.STRING_CLASS;
        userEvent.setValue(userInfo.getEvent());
        request.addProperty(userEvent);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.setOutputSoapObject(request);

        KeepAliveHttpsTransportSE keepAliveHttpsTransportSE = new KeepAliveHttpsTransportSE(Constants.NETWORK_IP, Constants.NETWORK_PORT, Constants.NETWORK_SERVICE_ADDRESS, Constants.NETWORK_TIMEOUT);
        keepAliveHttpsTransportSE.debug = true;

        try {
            keepAliveHttpsTransportSE.call(SOAP_ACTION, envelope);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
        try {
            SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();

            return userInfo;
        } catch (SoapFault soapFault) {
            soapFault.printStackTrace();
            System.out.println(keepAliveHttpsTransportSE.responseDump);
            return userInfo;
        }
    }

    public static boolean attach(String seed, String accountCode) throws IOException {
        String methodName = "attachAuthenticator";

        allowAllSSL();

        SoapObject request = new SoapObject(NAMESPACE, methodName);

        PropertyInfo userSeed = new PropertyInfo();
        userSeed.name = "seed";
        userSeed.type = PropertyInfo.STRING_CLASS;
        userSeed.setValue(seed);
        request.addProperty(userSeed);

        PropertyInfo userAccountCode = new PropertyInfo();
        userAccountCode.name = "accountCode";
        userAccountCode.type = PropertyInfo.STRING_CLASS;
        userAccountCode.setValue(accountCode);
        request.addProperty(userAccountCode);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.setOutputSoapObject(request);

        KeepAliveHttpsTransportSE keepAliveHttpsTransportSE = new KeepAliveHttpsTransportSE(Constants.NETWORK_IP, Constants.NETWORK_PORT, Constants.NETWORK_SERVICE_ADDRESS, Constants.NETWORK_TIMEOUT);
        keepAliveHttpsTransportSE.debug = true;

        try {
            keepAliveHttpsTransportSE.call(SOAP_ACTION, envelope);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
        try {
            SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
            return Boolean.parseBoolean(resultsRequestSOAP.toString());
        } catch (SoapFault soapFault) {
            soapFault.printStackTrace();
            System.out.println(keepAliveHttpsTransportSE.responseDump);
            return false;
        }
    }

    public static boolean changeSecret(String seed, String secretKey) throws IOException {
        String methodName = "changeSecretKey";

        allowAllSSL();

        SoapObject request = new SoapObject(NAMESPACE, methodName);

        PropertyInfo userSeed = new PropertyInfo();
        userSeed.name = "seed";
        userSeed.type = PropertyInfo.STRING_CLASS;
        userSeed.setValue(seed);
        request.addProperty(userSeed);

        PropertyInfo userSecretKey = new PropertyInfo();
        userSecretKey.name = "secretKey";
        userSecretKey.type = PropertyInfo.STRING_CLASS;
        userSecretKey.setValue(secretKey);
        request.addProperty(userSecretKey);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.setOutputSoapObject(request);

        KeepAliveHttpsTransportSE keepAliveHttpsTransportSE = new KeepAliveHttpsTransportSE(Constants.NETWORK_IP, Constants.NETWORK_PORT, Constants.NETWORK_SERVICE_ADDRESS, Constants.NETWORK_TIMEOUT);
        keepAliveHttpsTransportSE.debug = true;

        try {
            keepAliveHttpsTransportSE.call(SOAP_ACTION, envelope);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
        try {
            SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
            return Boolean.parseBoolean(resultsRequestSOAP.toString());
        } catch (SoapFault soapFault) {
            soapFault.printStackTrace();
            System.out.println(keepAliveHttpsTransportSE.responseDump);
            return false;
        }
    }

    final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    private static void trustAllHosts() {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }

            public void checkClientTrusted(X509Certificate[] chain,
                                           String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain,
                                           String authType) throws CertificateException {
            }
        }};

        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection
                    .setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static TrustManager[] trustManagers;

    public static class _FakeX509TrustManager implements
            javax.net.ssl.X509TrustManager {
        private static final X509Certificate[] _AcceptedIssuers =
                new X509Certificate[]{};

        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public boolean isClientTrusted(X509Certificate[] chain) {
            return (true);
        }

        public boolean isServerTrusted(X509Certificate[] chain) {
            return (true);
        }

        public X509Certificate[] getAcceptedIssuers() {
            return (_AcceptedIssuers);
        }
    }

    public static void allowAllSSL() {

        javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new
                HostnameVerifier() {
                    public boolean verify(String hostname, SSLSession
                            session) {
                        return true;
                    }
                });

        javax.net.ssl.SSLContext context = null;

        if (trustManagers == null) {
            trustManagers = new javax.net.ssl.TrustManager[]{new
                    _FakeX509TrustManager()};
        }

        try {
            context = javax.net.ssl.SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {

        } catch (KeyManagementException e) {

        }

        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
    }
}
